#!/usr/bin/env node

'use strict';

const { readFileSync, writeFileSync, existsSync, mkdirSync, cpSync } = require('node:fs');
const { cwd } = require('node:process');
const currentWorkingDir = cwd();
console.log(`Current directory: ${currentWorkingDir}`);
const userHome = require('node:os').homedir();
const { ncp } = require('ncp');
const { rimraf, rimrafSync, native, nativeSync } = require('rimraf');

console.log(process.argv);

function registerLocalPackage(currentWorkingDir) {
    const packageJsonFilePath = currentWorkingDir + '/package.json';

    if (!existsSync(packageJsonFilePath)) {
        console.warn(`package.json文件不存在!(${packageJsonFilePath})，无法进行npm包注册！`);
        return;
    }

    // 读取package.json文件，获取其中的名字和files属性
    const packageJsonStr = readFileSync(packageJsonFilePath, 'utf-8');
    let packageJson = {};
    try {
        packageJson = JSON.parse(packageJsonStr);
    } catch (error) {
        console.warn(`${packageJsonFilePath}文件存在，但是读取json失败，将忽略所有内容并覆写！`);
        packageJson = {};
    }

    console.log(`package.json: ${packageJson}`);

    // 获取名字
    const { name, files } = packageJson;
    console.log(`Name: ${name}`);
    console.log(`Files: ${files}`);
    if (!name) {
        console.warn('package.json文件中没有name属性，无法进行npm包注册！');
        return;
    }

    // 获取用户目录，创建或者写入一个文件.debugnpm
    const debugNpmFilePath = userHome + '/.debugnpm';
    // 如果debugNpmFilePath这个文件存在，则直接读取文件内容，并转化成JSON
    let debugNpmJson = {};
    if (existsSync(debugNpmFilePath)) {
        const debugNpmStr = readFileSync(debugNpmFilePath, 'utf-8');
        try {
            debugNpmJson = JSON.parse(debugNpmStr);
        } catch (error) {
            debugNpmJson = {};
        }
    }

    debugNpmJson.packages = debugNpmJson.packages || {};

    const config = {
        path: currentWorkingDir,
    };

    const configStr = JSON.stringify(config, undefined, '    ');

    if (debugNpmJson.packages[name]) {
        console.log(`\
    ${name}模块在debugnpm中的配置为，
    ${JSON.stringify(debugNpmJson.packages[name], undefined, '    ')}
    目前被替换为
    ${configStr}
    `
        );
    }

    debugNpmJson.packages[name] = config;

    writeFileSync(debugNpmFilePath, JSON.stringify(debugNpmJson, undefined, '    '));
    console.log(`debugnpm file path: ${debugNpmFilePath}`);
}

function copyLocalPackageToCwd(currentWorkingDir, packageName) {
    const packageJsonPath = currentWorkingDir + '/package.json';
    if (!existsSync(packageJsonPath)) {
        console.warn(`当前目录下找不到package.json，说明它并非一个npm工程，无法完成拷贝工作！`);
        return;
    }

    const nodeModulesDir = currentWorkingDir + '/node_modules';
    if (!existsSync(nodeModulesDir)) {
        consosle.warn(`node_modules目录不存在，单独拷贝恐怕没有意义，请先执行yarn或者npm i，把npm包下载下来后再执行本命令！`);
        return;
    }

    // 读取.debugnpm文件，获取pacakgeName对应的文件路径
    const debugNpmFilePath = userHome + '/.debugnpm';
    if (!existsSync(debugNpmFilePath)) {
        console.warn(`debugnpm文件不存在! 请先注册需要拷贝的npm包！注册方式是在npm工程下执行debugnpm.`);
        return;
    }

    const debugNpmStr = readFileSync(debugNpmFilePath, 'utf8');
    let debugNpmJson;
    try {
        debugNpmJson = JSON.parse(debugNpmStr);
    } catch (e) {
        console.warn(`.debugnpm解析出错！请先注册npm包！`);
    }

    if (!debugNpmJson) {
        console.warn(`!debugNpmJson`);
        return;
    }

    const packageConfig = debugNpmJson.packages[packageName];
    const pacakgeDir = packageConfig.path;
    if (!pacakgeDir || !existsSync(pacakgeDir)) {
        console.warn(`!pacakgeDir || !existsSync(pacakgeDir)`);
        return;
    }
    const packagePackageJsonPath = pacakgeDir + '/package.json';
    if (!existsSync(packagePackageJsonPath)) {
        console.warn(`packagePackageJsonPath不存在！`);
        return;
    }

    const packagePackageJsonStr = readFileSync(packagePackageJsonPath, 'utf8');
    let packagePackageJson = undefined;
    try {
        packagePackageJson = JSON.parse(packagePackageJsonStr);
    } catch (error) {
        console.warn(`packagePackageJsonStr解析出错！`);
        packagePackageJson = undefined;
    }
    if (!packagePackageJson) {
        console.warn(`packagePackageJsonStr解析出错！`);
        return;
    }

    const nodeModulesPackageDir = nodeModulesDir + '/' + packageName;
    if (existsSync(nodeModulesPackageDir)) {
        console.log(`${nodeModulesPackageDir}目录已存在，准备删除...`);
        rimrafSync(nodeModulesPackageDir);
        console.log(`${nodeModulesPackageDir}删除完成.`);
    }
    console.log(`创建目录${nodeModulesPackageDir}`);
    mkdirSync(nodeModulesPackageDir, { recursive: true, });

    const { files } = packagePackageJson;
    if (!files) {
        // 拷贝所有文件
        const source = pacakgeDir;
        const destination = nodeModulesPackageDir;
        console.log(`正在拷贝...`);
        console.log(`原目录${source}`);
        console.log(`目标目录${destination}`);
        ncp(source, destination, function (err) {
            if (err) {
                return console.error(err);
            }
            console.log('拷贝完成！');
        });
        console.log(`正在拷贝，请等待！`);
    } else {
        // 拷贝files中存在的文件
        for (const file of files) {
            const source = pacakgeDir + '/' + file;
            const destination = nodeModulesPackageDir + '/' + file;
            console.log(`正在拷贝...`);
            console.log(`原目录${source}`);
            if (!existsSync(source)) {
                console.warn(`原目录不存在，跳过！`)
                continue;
            }
            console.log(`目标目录${destination}`);
            // ncp(source, destination, function (err) {
            //     if (err) {
            //         console.error(`拷贝出错`);
            //         return console.error(err);
            //     }
            //     console.log(`${destination} 拷贝完成!`);
            // });
            cpSync(source, destination, { recursive: true });
            console.log(`正在拷贝，请等待！`);
        }
    }
}

if (process.argv.length < 3) {
    registerLocalPackage(currentWorkingDir);
} else {
    copyLocalPackageToCwd(currentWorkingDir, process.argv[2]);
}
